package br.com.statizo.financeiro.domain.repo.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import snoghert.db.util.PersistenceUtil;
import br.com.statizo.financeiro.domain.entity.impl.EntidadeAbstrata;
import br.com.statizo.financeiro.domain.repo.Repositorio;

public abstract class RepositorioAbstrato<E extends EntidadeAbstrata> implements Repositorio<E> {

	private Class<E> entityClass;
	private String entityName;
	
	protected EntityManager entityManager;
	protected PersistenceUtil persistenceUtility;
	
	public RepositorioAbstrato(PersistenceUtil persistenceUtility) {
		this.persistenceUtility = persistenceUtility;
		entityManagerRefresh();
		loadEntityProperties();
	}
	
	public List<E> getList() {
		return entityManager.createQuery("from " + entityName,entityClass).getResultList();
	}

	public E getById(Serializable id) {
		return entityManager.find(entityClass, id);
	}
	
	public E merge(E entity) {
		E e = entityManager.merge( entity );
		return e; 
	}
	
	public void persist(E entity) {
		entityManager.persist(entity);
	}
	
	public void remove(E entity) {
		entityManager.remove( entity );
	}
	
	public void remove(Serializable id){
		Query query = entityManager.createQuery("delete from " + entityName + " where id = :id");
		query.setParameter("id", id).executeUpdate();
	}
	
	public void beginTransaction(){
		entityManager.getTransaction().begin();
	}
	
	public void rollBack(){
		entityManager.getTransaction().rollback();
	}
	
	public int count(){
		Long total = entityManager.createQuery("select count(id) from " + entityName, Long.class).getSingleResult();
		return total.intValue();
	}
	
	public void entityManagerRefresh(){
		if(entityManager != null){
			entityManager.close();			
		}
		persistenceUtility.refreshEntityManager(this);
	}
	
	public void commit(){
		entityManager.getTransaction().commit();
	}
	
	
	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}
	
	@SuppressWarnings("unchecked")
	protected void loadEntityProperties(){
		ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); 
		this.entityClass = (Class<E>) type.getActualTypeArguments()[0];
		this.entityName = this.entityClass.toString().split("impl.")[1];
	}
	
}